// 1.1.2 字符串-C 风格字符串-方法
/**
 * C++ 提供了以下两种类型的字符串表示形式：
 *    C 风格字符串
 *    C++ 引入的 string 类类型
 * 
 * ------------------------
 * C 风格字符串
 * C 风格的字符串起源于 C 语言，并在 C++ 中继续得到支持。字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此，一个以 null 结尾的字符串，包含了组成字符串的字符。
 * 
 * 下面的声明和初始化创建了一个 RUNOOB 字符串。由于在数组的末尾存储了空字符，所以字符数组的大小比单词 RUNOOB 的字符数多一个。
    
    char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};

 * 依据数组初始化规则，您可以把上面的语句写成以下语句：
    char site[] = "RUNOOB";

 *
 * 以下是 C/C++ 中定义的字符串的内存表示：
 * 
 * 索引    0       1        2        3        4        5       6
 * 变量    R       U        N        O        O        B       \0
 * 地址 0x23451 0x23452  0x23453  0x23454  0x23455  0x23456  0x23457
 * 
 * 其实，您不需要把 null 字符放在字符串常量的末尾。C++ 编译器会在初始化数组时，自动把 \0 放在字符串的末尾。
 * 
 * 
 * ~~~~~~~~~~~~~~~~~~~~~~~~
 * 方法
 * C++ 中有大量的函数用来操作以 null 结尾的字符串:
 * 1. strcpy(s1, s2);
 * 复制字符串 s2 到字符串 s1。
 * 
 * 2. strcat(s1, s2);
 * 连接字符串 s2 到字符串 s1 的末尾。连接字符串也可以用 + 号，例如:
    
    string str1 = "runoob";
    string str2 = "google";
    string str = str1 + str2;

 * 
 * 3. strlen(s1);
 * 返回字符串 s1 的长度。
 * 
 * 4. strcmp(s1, s2);
 * 如果 s1 和 s2 是相同的，则返回 0；如果 s1<s2 则返回值小于 0；如果 s1>s2 则返回值大于 0。
 * 
 * 5. strchr(s1, ch);
 * 返回一个指针，指向字符串 s1 中字符 ch 的第一次出现的位置。
 * 
 * 6. strstr(s1, s2);
 * 返回一个指针，指向字符串 s1 中字符串 s2 的第一次出现的位置。
 * 
 * 下面的实例使用了上述的一些函数：
*/

#include <iostream>
#include <cstring>

int main(void)
{
  char str1[] = "RUNOOB";
  char str2[] = "google";

  char str3[20];
  // char str4[7];

  strcpy(str3, str1);
  std::cout << "strcpy(str3,str1) str3:" << str3 << std::endl;

  if (strcmp(str1, str3) == 0)
  {
    std::cout << "str1 == str3" << std::endl;
  }
  else
  {
    std::cout << "str1 != str3" << std::endl;
  }

  if (strcmp("runoobhhh", "runoob") == 0)
  {
    std::cout << "runoob == runoobhhh" << std::endl;
  }
  else
  {
    std::cout << "runoob != runoobhhh" << std::endl;
  }

  // 这个可以用来判断是否为子字符串
  if (strncmp("runoobhhh", "runoob", 6) == 0)
  {
    std::cout << "runoob == runoobhhh" << std::endl;
  }
  else
  {
    std::cout << "runoob != runoobhhh" << std::endl;
  }

  // strncmp函数为字符串比较函数，字符串大小的比较是以ASCII 码表上的顺序来决定，此顺序亦为字符的值。其函数声明为int strncmp ( const char * str1, const char * str2, size_t n );功能是把 str1 和 str2 进行比较，最多比较前 n 个字节，若str1与str2的前n个字符相同，则返回0；若s1大于s2，则返回大于0的值；若s1 小于s2，则返回小于0的值。

  strcat(str3, str2);
  std::cout << "strcat(str3,str2); str3:" << str3 << std::endl;

  // std::cout << "str3 + str2; str3:" << (str3 + str2) << std::endl; // error: invalid operands of types 'char [20]' and 'char [7]' to binary 'operator+'

  std::cout << "str3 length: " << strlen(str3) << std::endl;

  // -----查询字符串中某个字符第一次出现的位置

  char *ptr1 = strchr(str1, 'o');

  // char * 输出cout问题 ，强制转换成非char *型，如(void *)

  std::cout << "str1 runoob 中 o 首次出现位置 ptr1:" << (void *)ptr1 << std::endl; // 找不到就是0

  ptr1 = strchr(str1, 'O');
  std::cout << "str1 runoob 中 O 首次出现位置 ptr1:" << (void *)ptr1 << std::endl; // 0x61fe04

  // -----查询字符串中某个字符串第一次出现的位置

  char *ptr2 = strstr(str2, "xx");
  std::cout << "str2 google 中 xx 首次出现位置 ptr2:" << (void *)ptr2 << std::endl; // 找不到 0

  ptr2 = strstr(str2, "gl");
  std::cout << "str2 google 中 gl 首次出现位置 ptr2:" << (void *)ptr2 << std::endl; // 0x61fdf5

  printf("-----------end-------------\n");
  return 0;
}
